package service

import (
	"awesomeProject/internal/model"
	"awesomeProject/internal/repository"
	"awesomeProject/pkg/auth"
	"awesomeProject/pkg/errors"
	"context"
	"regexp"
	"strings"
	"time"

	"golang.org/x/crypto/bcrypt"
)

type UserService interface {
	// 用户注册和认证
	Register(ctx context.Context, req *RegisterRequest) (*model.User, error)
	Login(ctx context.Context, req *LoginRequest) (string, error)
	RefreshToken(ctx context.Context, tokenString string) (string, error)

	// 用户信息管理
	GetProfile(ctx context.Context, userID uint) (*model.User, error)
	UpdateProfile(ctx context.Context, userID uint, req *UpdateProfileRequest) error
	ChangePassword(ctx context.Context, userID uint, req *ChangePasswordRequest) error
	DeleteAccount(ctx context.Context, userID uint) error

	// 用户列表
	GetUserList(ctx context.Context, page, pageSize int) ([]*model.User, int64, error)
}

type userService struct {
	userRepo   repository.UserRepository
	jwtManager *auth.JWTManager
}

// NewUserService 创建用户服务实例
func NewUserService(userRepo repository.UserRepository, jwtManager *auth.JWTManager) UserService {
	return &userService{
		userRepo:   userRepo,
		jwtManager: jwtManager,
	}
}

// 请求结构体定义
type RegisterRequest struct {
	Username string `json:"username" binding:"required,min=3,max=20"`
	Email    string `json:"email" binding:"required,email"`
	Password string `json:"password" binding:"required,min=6,max=20"`
	Nickname string `json:"nickname" binding:"omitempty,max=50"`
}

type LoginRequest struct {
	Username string `json:"username" binding:"required"`
	Password string `json:"password" binding:"required"`
}

type UpdateProfileRequest struct {
	Nickname string `json:"nickname" binding:"omitempty,max=50"`
	Email    string `json:"email" binding:"omitempty,email"`
	Avatar   string `json:"avatar" binding:"omitempty,url"`
	Bio      string `json:"bio" binding:"omitempty,max=200"`
}

type ChangePasswordRequest struct {
	OldPassword string `json:"old_password" binding:"required"`
	NewPassword string `json:"new_password" binding:"required,min=6,max=20"`
}

type ListUsersRequest struct {
	Page  int `json:"page"`
	Limit int `json:"limit"`
}

// Register 用户注册
func (s *userService) Register(ctx context.Context, req *RegisterRequest) (*model.User, error) {
	// 验证用户名格式
	if !isValidUsername(req.Username) {
		return nil, errors.ErrInvalidUsername
	}

	// 验证密码强度
	if !isValidPassword(req.Password) {
		return nil, errors.ErrPasswordTooWeak
	}

	// 检查用户名是否已存在
	existingUser, err := s.userRepo.GetByUsername(ctx, req.Username)
	if err != nil && err != errors.ErrUserNotFound {
		return nil, errors.ErrInternalError
	}
	if existingUser != nil {
		return nil, errors.ErrUserExists
	}

	// 检查邮箱是否已存在
	existingUser, err = s.userRepo.GetByEmail(ctx, req.Email)
	if err != nil && err != errors.ErrUserNotFound {
		return nil, errors.ErrInternalError
	}
	if existingUser != nil {
		return nil, errors.ErrEmailExists
	}

	// 加密密码
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
	if err != nil {
		return nil, errors.ErrInternalError
	}

	// 创建用户
	user := &model.User{
		Username:     strings.TrimSpace(req.Username),
		Email:        strings.TrimSpace(req.Email),
		PasswordHash: string(hashedPassword),
		Nickname:     strings.TrimSpace(req.Nickname),
		Status:       1, // 激活状态
		CreatedAt:    time.Now(),
		UpdatedAt:    time.Now(),
	}

	if user.Nickname == "" {
		user.Nickname = user.Username
	}

	return s.userRepo.Create(ctx, user)
}

// Login 用户登录
func (s *userService) Login(ctx context.Context, req *LoginRequest) (string, error) {
	// 获取用户信息
	user, err := s.userRepo.GetByUsername(ctx, req.Username)
	if err != nil {
		if err == errors.ErrUserNotFound {
			return "", errors.ErrInvalidCredentials
		}
		return "", errors.ErrInternalError
	}

	// 验证密码
	err = bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(req.Password))
	if err != nil {
		return "", errors.ErrInvalidCredentials
	}

	// 检查用户状态
	if user.Status != 1 {
		return "", errors.ErrUserDisabled
	}

	// 更新最后登录时间
	now := time.Now()
	user.LastLoginAt = &now
	s.userRepo.Update(ctx, user.ID, user)

	// 生成JWT token
	token, err := s.jwtManager.GenerateToken(user)
	if err != nil {
		return "", errors.ErrInternalError
	}

	return token, nil
}

// RefreshToken 刷新JWT token
func (s *userService) RefreshToken(ctx context.Context, tokenString string) (string, error) {
	// 使用JWT管理器刷新token
	newToken, err := s.jwtManager.RefreshToken(tokenString)
	if err != nil {
		return "", errors.ErrInvalidToken
	}
	return newToken, nil
}

// GetProfile 获取用户资料
func (s *userService) GetProfile(ctx context.Context, userID uint) (*model.User, error) {
	return s.userRepo.GetByID(ctx, userID)
}

// UpdateProfile 更新用户资料
func (s *userService) UpdateProfile(ctx context.Context, userID uint, req *UpdateProfileRequest) error {
	// 获取当前用户信息
	user, err := s.userRepo.GetByID(ctx, userID)
	if err != nil {
		return err
	}

	// 如果更新邮箱，检查邮箱是否已被其他用户使用
	if req.Email != "" && req.Email != user.Email {
		existingUser, err := s.userRepo.GetByEmail(ctx, req.Email)
		if err != nil && err != errors.ErrUserNotFound {
			return errors.ErrInternalError
		}
		if existingUser != nil && existingUser.ID != userID {
			return errors.ErrEmailExists
		}
		user.Email = strings.TrimSpace(req.Email)
	}

	// 更新其他字段
	if req.Nickname != "" {
		user.Nickname = strings.TrimSpace(req.Nickname)
	}
	if req.Avatar != "" {
		user.Avatar = strings.TrimSpace(req.Avatar)
	}
	if req.Bio != "" {
		user.Bio = strings.TrimSpace(req.Bio)
	}

	user.UpdatedAt = time.Now()

	return s.userRepo.Update(ctx, userID, user)
}

// ChangePassword 修改密码
func (s *userService) ChangePassword(ctx context.Context, userID uint, req *ChangePasswordRequest) error {
	// 获取用户信息
	user, err := s.userRepo.GetByID(ctx, userID)
	if err != nil {
		return err
	}

	// 验证旧密码
	err = bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(req.OldPassword))
	if err != nil {
		return errors.ErrInvalidCredentials
	}

	// 验证新密码强度
	if !isValidPassword(req.NewPassword) {
		return errors.ErrWeakPassword
	}

	// 加密新密码
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.NewPassword), bcrypt.DefaultCost)
	if err != nil {
		return errors.ErrInternalError
	}

	user.PasswordHash = string(hashedPassword)
	user.UpdatedAt = time.Now()

	return s.userRepo.Update(ctx, userID, user)
}

// DeleteAccount 删除账户
func (s *userService) DeleteAccount(ctx context.Context, userID uint) error {
	return s.userRepo.Delete(ctx, userID)
}

// GetUserList 获取用户列表
func (s *userService) GetUserList(ctx context.Context, page, pageSize int) ([]*model.User, int64, error) {
	if page <= 0 {
		page = 1
	}
	if pageSize <= 0 || pageSize > 100 {
		pageSize = 20
	}

	return s.userRepo.List(ctx, page, pageSize)
}

// 辅助函数

// isValidUsername 验证用户名格式
func isValidUsername(username string) bool {
	// 用户名只能包含字母、数字、下划线，长度3-20
	matched, _ := regexp.MatchString(`^[a-zA-Z0-9_]{3,20}$`, username)
	return matched
}

// isValidPassword 验证密码强度
func isValidPassword(password string) bool {
	// 密码长度6-20，至少包含字母和数字
	if len(password) < 6 || len(password) > 20 {
		return false
	}

	hasLetter := regexp.MustCompile(`[a-zA-Z]`).MatchString(password)
	hasNumber := regexp.MustCompile(`[0-9]`).MatchString(password)

	return hasLetter && hasNumber
}
